/*

* ------------------------------------------------------------------------
* ------------------------------------------------------------------------
* |     Smart-Shop开源商城系统/ Java商城-首选电商平台系统 请务必保留此注释头信息
* |     开源地址: https://gitee.com/ningbo-qishan/gruul-mall
* ------------------------------------------------------------------------
* ------------------------------------------------------------------------
* |     可正常分享和学习源码,未经授权 不可商用！
* |     商业版中台购买/开源版商业授权 联系技术客服
* |     官网:  https://www.73app.cn/
* ------------------------------------------------------------------------
* ------------------------------------------------------------------------
* |     Copyright (c) 2016-2999 宁波启山智软科技有限公司
* |     版权所有 ,侵权必究！
* ------------------------------------------------------------------------

*/
package com.medusa.gruul.platform.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.medusa.gruul.common.core.constant.CommonConstants;
import com.medusa.gruul.common.core.constant.enums.AuthCodeEnum;
import com.medusa.gruul.common.core.exception.ServiceException;
import com.medusa.gruul.common.core.util.LocalDateTimeUtils;
import com.medusa.gruul.common.core.util.PageUtils;
import com.medusa.gruul.common.core.validator.ValidatorUtils;
import com.medusa.gruul.common.core.validator.group.AddGroup;
import com.medusa.gruul.common.core.validator.group.UpdateGroup;
import com.medusa.gruul.platform.api.entity.*;
import com.medusa.gruul.platform.mapper.AgentInfoMapper;
import com.medusa.gruul.platform.model.dto.CardBankDto;
import com.medusa.gruul.platform.model.dto.agent.*;
import com.medusa.gruul.platform.model.vo.agent.*;
import com.medusa.gruul.platform.service.*;
import com.medusa.gruul.platform.stp.StpAgentUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 代理商信息表 服务实现类
 * </p>
 *
 * @author whh
 * @since 2020-10-04
 */
@Service
public class AgentInfoServiceImpl extends ServiceImpl<AgentInfoMapper, AgentInfo> implements IAgentInfoService {

    @Autowired
    private IAgentRuleService agentRuleService;
    @Autowired
    private IAgentBankService agentBankService;
    @Autowired
    private ISendCodeService sendCodeService;
    @Autowired
    private IAccountInfoService accountInfoService;
    @Autowired
    private IAgentStatisticsService agentStatisticsService;
    @Autowired
    private IAgentVerifyService agentVerifyService;
    @Autowired
    private IAgentTransferLogService agentTransferLogService;
    @Autowired
    private IPlatformShopInfoService shopInfoService;
    @Autowired
    private IAgentNoticeService agentNoticeService;
    @Autowired
    private ISysShopPackageOrderService sysShopPackageOrderService;

    @Override
    public AgentInfo getByAccount(String account) {
        return this.getOne(new QueryWrapper<AgentInfo>().eq("account", account));
    }

    @Override
    public Long newAccount(AgenInfoDto dto, String code, Integer registerType) {
        AgentInfo agentInfo = new AgentInfo();
        BeanUtil.copyProperties(dto, agentInfo);
        agentInfo.setCode(code);
        BigDecimal amoun = BigDecimal.valueOf(0);
        agentInfo.setAvailableAmount(amoun);
        agentInfo.setFreezeAmount(amoun);
        agentInfo.setRegisterType(registerType);
        agentInfo.setSubLedgerAmount(amoun);
        agentInfo.setUsedAmount(amoun);
        agentInfo.setStatus(CommonConstants.NUMBER_ONE);
        agentInfo.setType(dto.getAgentType());
        agentInfo.setParentId(CommonConstants.NUMBER_ZERO.longValue());
        this.save(agentInfo);
        //新增代理目标
        agentRuleService.newAgentRule(dto.getAgentTarget(), agentInfo.getId(), CommonConstants.NUMBER_ONE);
        //新增升级条件
        agentRuleService.newAgentRule(dto.getAgentUpgrade(), agentInfo.getId(), CommonConstants.NUMBER_TWO);
        agentBankService.newBank(dto.getBankInfo(), agentInfo.getId());
        agentStatisticsService.newStatistics(agentInfo.getId());

        return agentInfo.getId();
    }


    @Override
    public void motifyInfo(AgenInfoDto dto) {
        AgentInfo agentInfo;
        Boolean state = Boolean.TRUE;
        if (dto.getId() == null || dto.getId() == 0) {
            ValidatorUtils.validateEntity(dto, AddGroup.class);
            agentInfo = new AgentInfo();
            agentInfo.setCode(agentVerifyService.getCode());
            if (this.getByAccount(dto.getAccount()) != null) {
                throw new ServiceException("账号已存在");
            }
            agentInfo.setStatus(CommonConstants.NUMBER_ONE);
            BigDecimal amoun = BigDecimal.valueOf(0);
            agentInfo.setAvailableAmount(amoun);
            agentInfo.setFreezeAmount(amoun);
            agentInfo.setRegisterType(CommonConstants.NUMBER_THREE);
            agentInfo.setSubLedgerAmount(amoun);
            agentInfo.setUsedAmount(amoun);
            agentInfo.setParentId(CommonConstants.NUMBER_ZERO.longValue());
        } else {
            ValidatorUtils.validateEntity(dto, UpdateGroup.class);
            agentInfo = this.getById(dto.getId());
            if (agentInfo == null) {
                throw new ServiceException("无效账号信息");
            }
            //修改了账号则需判断账号是否已存在
            if (!agentInfo.getAccount().equals(dto.getAccount())) {
                if (this.getByAccount(dto.getAccount()) != null) {
                    throw new ServiceException("账号已存在");
                }
            }
            state = Boolean.FALSE;
        }
        dto.validate();
        CardBankDto bankInfo = dto.getBankInfo();
        sendCodeService.certificateCheck(bankInfo.getCertificate(), bankInfo.getCardPhone(), AuthCodeEnum.AGENT_BANK_VALIDATE.getType());
        //修改代理自身信息
        BeanUtil.copyProperties(dto, agentInfo);
        agentInfo.setType(dto.getAgentType());

        this.saveOrUpdate(agentInfo);
        if (state) {
            //修改代理规则 规则类型 1目标规则  2-升级条件
            agentRuleService.newAgentRule(dto.getAgentTarget(), agentInfo.getId(), CommonConstants.NUMBER_ONE);
            agentRuleService.newAgentRule(dto.getAgentUpgrade(), agentInfo.getId(), CommonConstants.NUMBER_TWO);
            //修改代理银行卡
            agentBankService.newBank(dto.getBankInfo(), agentInfo.getId());
            agentStatisticsService.newStatistics(agentInfo.getId());
        } else {
            //修改代理规则 规则类型 1目标规则  2-升级条件
            agentRuleService.updateRule(agentInfo.getId(), dto.getAgentTarget(), CommonConstants.NUMBER_ONE);
            agentRuleService.updateRule(agentInfo.getId(), dto.getAgentUpgrade(), CommonConstants.NUMBER_TWO);
            //修改代理银行卡
            agentBankService.updateBank(dto.getBankInfo());
        }

    }

    @Override
    public PageUtils<AgentInfosVo> agentInfos(Integer page, Integer size, String startTime, String endTime, String search, Integer type, Long parentId) {
        IPage<AgentInfoListDto> resultIpage = this.baseMapper.selectByList(new Page<>(page, size), startTime, endTime, search, type, parentId);
        // 封装返回对象
        PageUtils<AgentInfosVo> result = new PageUtils<>(null, (int) resultIpage.getTotal(), (int) resultIpage.getSize(), (int) resultIpage.getCurrent());
        // 拷贝部分属性
        if (CollectionUtil.isEmpty(resultIpage.getRecords())) {
            return result;
        }
        List<AgentInfosVo> infosVos = resultIpage.getRecords().stream().map(obj -> {
            return BeanUtil.toBean(obj, AgentInfosVo.class);
        }).collect(Collectors.toList());
        result.setList(infosVos);
        return result;

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchOption(BatchOptionDto discountDto) {
        //type=1 设置折扣  type=2批量设置目标  type=3 批量启用  type=4 批量停用  type=5批量删除 type=6 迁移渠道商  type=7迁移商户
        AgentInfo agentInfo = new AgentInfo();
        switch (discountDto.getOptionType()) {
            case 0:
                if (discountDto.getOptionType() >= CommonConstants.NUMBER_ONE && discountDto.getOptionType() <= CommonConstants.NUMBER_FIVE) {
                    if (CollectionUtil.isEmpty(discountDto.getAgentIds())) {
                        throw new ServiceException("请正确选择代理");
                    }
                } else if (discountDto.getOptionType() >= CommonConstants.NUMBER_SIX && discountDto.getOptionType() <= CommonConstants.NUMBER_SEVEN) {
                    throw new ServiceException("请正确选择代理");
                }
            case 1:
                if (discountDto.getDiscount() == null) {
                    throw new ServiceException("折扣错误");
                }
                agentInfo.setDiscount(discountDto.getDiscount());
                this.update(agentInfo, new UpdateWrapper<AgentInfo>().in("id", discountDto.getAgentIds()));
                break;
            case 2:
                for (Long agentId : discountDto.getAgentIds()) {
                    agentRuleService.updateRule(agentId, discountDto.getAgentTarget(), 1);
                }
                break;
            case 3:
                agentInfo.setStatus(CommonConstants.NUMBER_ONE);
                this.update(agentInfo, new UpdateWrapper<AgentInfo>().in("id", discountDto.getAgentIds()));
                break;
            case 4:
                agentInfo.setStatus(CommonConstants.NUMBER_THREE);
                this.update(agentInfo, new UpdateWrapper<AgentInfo>().in("id", discountDto.getAgentIds()));
                break;
            case 5:
                removeAgent(discountDto.getAgentIds());

                break;
            case 6:
                if (CollectionUtil.isEmpty(discountDto.getChannelIds())) {
                    throw new ServiceException("请正确选择渠道商");
                }
                migrationAgentParent(discountDto.getAgentId(), discountDto.getChannelIds());
                break;
            case 7:
                if (CollectionUtil.isEmpty(discountDto.getAccountIds())) {
                    throw new ServiceException("请正确选择商户");
                }
                migrationAccount(discountDto.getAgentId(), discountDto.getAccountIds());
                break;
            default:
                break;
        }

    }

    /**
     * 删除指定代理
     *
     * @param agentIds 代理id
     */
    private void removeAgent(List<Long> agentIds) {
        List<AgentInfo> agentInfos = this.baseMapper.selectBatchIds(agentIds);
        if (CollectionUtil.isEmpty(agentIds)) {
            return;
        }
        List<AccountInfo> infos = accountInfoService.list(new QueryWrapper<AccountInfo>().in("me_agent_id", agentIds));
        if (CollectionUtil.isNotEmpty(infos)) {
            for (AccountInfo info : infos) {
                accountInfoService.update(new UpdateWrapper<AccountInfo>()
                        .set("me_agent_id", null)
                        .eq("id", info.getId()));
            }
        }
        //删除指定代理信息
        for (AgentInfo agentInfo : agentInfos) {
            this.remove(new UpdateWrapper<AgentInfo>().eq("id", agentInfo.getId()));
            AgentStatistics statistics = agentStatisticsService.getByAgentId(agentInfo.getId());
            if (statistics.getShopInfoCount() > CommonConstants.NUMBER_ZERO) {
                throw new ServiceException("存在所属商户无法删除");
            }
            if (agentInfo.getType().equals(CommonConstants.NUMBER_ONE)) {
                if (statistics.getChannalCount() > CommonConstants.NUMBER_ZERO) {
                    throw new ServiceException("代理商存在下级渠道商无法删除");
                }
            }
            //如果是间接渠道商需要减少上级代理的渠道商数据
            if (agentInfo.getType().equals(CommonConstants.NUMBER_THREE)) {
                statistics = agentStatisticsService.getByAgentId(agentInfo.getParentId());
                statistics.subChannalCount(CommonConstants.NUMBER_ONE);
                statistics.updateById();
            }

        }

    }

    /**
     * 迁移商户
     *
     * @param agentId    目标代理id
     * @param accountIds 迁移商户id
     */
    private void migrationAccount(Long agentId, List<Long> accountIds) {
        if (agentId == null || agentId == 0) {
            throw new ServiceException("未正确选择代理");
        }
        AgentInfo agentInfo = this.getById(agentId);
        if (agentInfo == null) {
            throw new ServiceException("无效的代理数据");
        }
        List<AccountInfo> accountInfos = accountInfoService.listByIds(accountIds);
        if (CollectionUtil.isEmpty(accountInfos)) {
            throw new ServiceException("无效用户数据");
        }
        if (accountInfos.size() != accountIds.size()) {
            throw new ServiceException("数据选择异常");
        }
        Integer toType = CommonConstants.NUMBER_TWO;
        if (agentInfo.getType().equals(CommonConstants.NUMBER_ZERO)) {
            toType = CommonConstants.NUMBER_ONE;
        }
        AgentStatistics agentStatistics = agentStatisticsService.getByAgentId(agentId);
        Integer sum = 0;
        for (AccountInfo accountInfo : accountInfos) {
            Integer count = shopInfoService.getByAccountIdShopCount(accountInfo.getId());
            //原本代理统计数据需去除
            if (accountInfo.getAgentId() != null && accountInfo.getAgentId() > 0) {
                boolean isSame = accountInfo.getAgentId().equals(agentId);
                if (isSame) {
                    continue;
                } else {
                    AgentStatistics old = agentStatisticsService.getByAgentId(accountInfo.getAgentId());
                    old.subShopInfoCount(CommonConstants.NUMBER_ONE);
                    old.subAppInfoCount(count);
                    old.updateById();
                }
            }
            AccountInfo up = new AccountInfo();
            up.setId(accountInfo.getId());
            up.setAgentId(agentInfo.getId());
            accountInfoService.updateById(up);
            //增加现有店铺数量以及商户数量
            sum += 1;
            agentStatistics.sumAppInfoCount(count);
            agentTransferLogService.addLog(accountInfo.getId(), CommonConstants.NUMBER_ONE, toType, agentInfo.getId());
        }
        if (sum > 0) {
            agentStatistics.sumShopInfoCount(sum);
            agentStatistics.updateById();
        }
    }

    /**
     * 渠道商迁移
     *
     * @param agentId    目标代理id
     * @param channelIds 迁移对象
     */
    private void migrationAgentParent(Long agentId, List<Long> channelIds) {
        if (agentId == null || agentId == 0) {
            throw new ServiceException("未正确选择代理");
        }
        AgentInfo agentInfo = this.getById(agentId);
        if (agentInfo == null) {
            throw new ServiceException("无效的代理数据");
        }
        if (!agentInfo.getType().equals(CommonConstants.NUMBER_ONE)) {
            throw new ServiceException("非代理账号");
        }
        Integer sum = 0;
        for (Long channelId : channelIds) {
            AgentInfo info = this.getById(channelId);
            //如果已经是该代理下的直接进行下一个
            if (info.getParentId() != null && info.getParentId() > 0) {
                boolean isSame = info.getParentId().equals(agentId);
                if (isSame) {
                    continue;
                } else {
                    //如果是代理之下的渠道商则需要为父级代理的渠道商数量减少
                    AgentStatistics parent = agentStatisticsService.getByAgentId(info.getParentId());
                    parent.subChannalCount(CommonConstants.NUMBER_ONE);
                    parent.updateById();
                }
            }
            AgentInfo up = new AgentInfo();
            up.setId(info.getId());
            up.setParentId(agentId);
            //直属渠道商迁移之后变为间接渠道商
            if (info.getType().equals(CommonConstants.NUMBER_TWO)) {
                up.setType(CommonConstants.NUMBER_THREE);
            }
            this.updateById(up);
            agentTransferLogService.addLog(info.getId(), CommonConstants.NUMBER_TWO, CommonConstants.NUMBER_THREE, agentId);
            sum += 1;
        }
        //增加渠道商统计
        if (sum > 0) {
            AgentStatistics agentStatistics = agentStatisticsService.getByAgentId(agentId);
            agentStatistics.sumChannalCount(sum);
            agentStatistics.updateById();
        }

    }

    /**
     * 获取某个代理下的所有下级渠道商
     *
     * @param agentId 代理id
     * @return 数量
     */
    private Integer countParentIdCount(Long agentId) {
        return this.getBaseMapper().selectCount(new QueryWrapper<AgentInfo>()
                .eq("parent_id", agentId)
                .eq("type", CommonConstants.NUMBER_TWO));
    }

    @Override
    public String login(AgentLoginDto agentLoginDto) {
        AgentInfo agentInfo = this.getByAccount(agentLoginDto.getAccount());
        if (agentInfo == null) {
            throw new ServiceException("账号或密码错误!");
        }
        if (!agentInfo.getPwd().equals(agentLoginDto.getPassword())) {
            throw new ServiceException("账号或密码错误!");
        }
        if (agentInfo.getStatus().equals(CommonConstants.NUMBER_THREE)) {
            throw new ServiceException("账号异常，请联系客服");
        }
        if (LocalDateTimeUtils.getSecondsByTime(agentInfo.getNextDueTime()) < LocalDateTimeUtils.getSecondsByTime(LocalDateTime.now())) {
            throw new ServiceException("账号到期，请联系客服");
        }
        StpAgentUtil.setLoginId(agentInfo.getId());
        return StpAgentUtil.getTokenValue();
    }

    @Override
    public AgentInfoVo agentInfo() {
        AgentInfo agentInfo = this.getById(StpAgentUtil.getLoginIdAsLong());
        AgentInfoVo vo = BeanUtil.toBean(agentInfo, AgentInfoVo.class);
        List<AgentRule> agentTarget = agentRuleService.getByAgenInfoIdAndRuleClass(agentInfo.getId(), CommonConstants.NUMBER_ONE);
        if (CollectionUtil.isNotEmpty(agentTarget)) {
            vo.setAgentTarget(agentTarget.stream()
                    .filter(obj -> obj.getUseRule().equals(CommonConstants.NUMBER_ONE))
                    .map(obj -> BeanUtil.toBean(obj, AgentRuleVo.class))
                    .collect(Collectors.toList()));
        }
        //渠道商需查出升级条件
        if (!agentInfo.getType().equals(CommonConstants.NUMBER_ONE)) {
            List<AgentRule> agentUpgrade = agentRuleService.getByAgenInfoIdAndRuleClass(agentInfo.getId(), CommonConstants.NUMBER_TWO);
            if (CollectionUtil.isNotEmpty(agentUpgrade)) {
                vo.setAgentUpgrade(agentUpgrade.stream()
                        .filter(obj -> obj.getUseRule().equals(CommonConstants.NUMBER_ONE))
                        .map(obj -> BeanUtil.toBean(obj, AgentRuleVo.class)).collect(Collectors.toList()));
            }
        }
        //获取未读消息
        int count = agentNoticeService.count(new QueryWrapper<AgentNotice>().eq("agent_info_id", agentInfo.getId())
                .eq("is_read", CommonConstants.NUMBER_ZERO));
        vo.setNotRead(count);
        return vo;
    }

    @Override
    public void agentAddChannel(AgentAddChannelDto agentAddChannelDto) {
        AgentInfo parentAgent = this.getById(StpAgentUtil.getLoginIdAsLong());
        if (!parentAgent.getType().equals(CommonConstants.NUMBER_ONE)) {
            throw new ServiceException("无权限添加");
        }
        if (!parentAgent.getStatus().equals(CommonConstants.NUMBER_ONE)) {
            throw new ServiceException("账号当前无法进行操作");
        }
        if (agentAddChannelDto.getId() != null && agentAddChannelDto.getId() > 0) {
            ValidatorUtils.validateEntity(agentAddChannelDto, UpdateGroup.class);
            CardBankDto bankInfo = agentAddChannelDto.getBankInfo();
            sendCodeService.certificateCheck(bankInfo.getCertificate(), bankInfo.getCardPhone(), AuthCodeEnum.AGENT_BANK_VALIDATE.getType());
            AgentInfo agentInfo = this.getById(agentAddChannelDto.getId());
            if (agentInfo == null) {
                throw new ServiceException("无效账号信息");
            }
            //是否是当前代理下的渠道商
            if (!agentInfo.getParentId().equals(parentAgent.getId())) {
                throw new ServiceException("无效账号信息");
            }
            //修改了账号则需判断账号是否已存在
            if (!agentInfo.getAccount().equals(agentAddChannelDto.getAccount())) {
                if (this.getByAccount(agentAddChannelDto.getAccount()) != null) {
                    throw new ServiceException("账号已存在");
                }
            }
            AgentInfo accountInfo = BeanUtil.toBean(agentAddChannelDto, AgentInfo.class);
            this.updateById(accountInfo);
            //修改代理银行卡
            agentBankService.updateBank(agentAddChannelDto.getBankInfo());
        } else {
            ValidatorUtils.validateEntity(agentAddChannelDto, AddGroup.class);
            CardBankDto bankInfo = agentAddChannelDto.getBankInfo();
            sendCodeService.certificateCheck(bankInfo.getCertificate(), bankInfo.getCardPhone(), AuthCodeEnum.AGENT_BANK_VALIDATE.getType());
            if (this.getByAccount(agentAddChannelDto.getAccount()) != null) {
                throw new ServiceException("该账号已被其他用户注册");
            }

            String code = agentVerifyService.getCode();
            AgentInfo agentInfo = new AgentInfo();
            BeanUtil.copyProperties(agentAddChannelDto, agentInfo);
            agentInfo.setCode(code);
            agentInfo.setType(CommonConstants.NUMBER_THREE);
            agentInfo.setDiscount(BigDecimal.valueOf(60));
            agentInfo.setIsAutoTimes(CommonConstants.NUMBER_ONE);
            agentInfo.setAgentShareProfit(0);
            agentInfo.setChannelShareProfit(0);
            BigDecimal amoun = BigDecimal.valueOf(0);
            agentInfo.setAvailableAmount(amoun);
            agentInfo.setFreezeAmount(amoun);
            agentInfo.setSubLedgerAmount(amoun);
            agentInfo.setUsedAmount(amoun);
            agentInfo.setStatus(CommonConstants.NUMBER_ONE);
            agentInfo.setParentId(parentAgent.getId());
            agentInfo.setRegisterType(CommonConstants.NUMBER_THREE);
            this.save(agentInfo);
            agentBankService.newBank(agentAddChannelDto.getBankInfo(), agentInfo.getId());
            //新增代理目标(间接渠道商不使用规则)
            agentRuleService.newAgentRule(null, agentInfo.getId(), CommonConstants.NUMBER_ONE);
            //新增升级条件(间接渠道商不使用规则)
            agentRuleService.newAgentRule(null, agentInfo.getId(), CommonConstants.NUMBER_TWO);
            AgentStatistics statistics = new AgentStatistics();
            statistics.setAgentInfoId(agentInfo.getId());
            BigDecimal decimal = new BigDecimal("0.0");
            statistics.setTotalSalePrice(decimal);
            statistics.setTotalSaleCount(CommonConstants.NUMBER_ZERO);
            statistics.setCommissionAmount(decimal);
            statistics.setChannalCount(CommonConstants.NUMBER_ZERO);
            statistics.setShopInfoCount(CommonConstants.NUMBER_ZERO);
            statistics.setAppInfoCount(CommonConstants.NUMBER_ZERO);
            agentStatisticsService.save(statistics);
        }


    }

    @Override
    public PageUtils<ChannelInfoVo> channel(Integer page, Integer size, String startTime, String endTime, String search) {
        long agentId = StpAgentUtil.getLoginIdAsLong();
        AgentInfo agentInfo = this.getById(agentId);
        if (!agentInfo.getType().equals(CommonConstants.NUMBER_ONE)) {
            throw new ServiceException("请确认代理身份");
        }
        IPage<AgentInfoListDto> resultIpage = this.baseMapper.selectByList(new Page<>(page, size),
                startTime, endTime, search, CommonConstants.NUMBER_THREE, agentId);
        // 封装返回对象
        PageUtils<ChannelInfoVo> result = new PageUtils<>(null, (int) resultIpage.getTotal(), (int) resultIpage.getSize(), (int) resultIpage.getCurrent());
        // 拷贝部分属性
        if (CollectionUtil.isEmpty(resultIpage.getRecords())) {
            return result;
        }
        List<ChannelInfoVo> infosVos = resultIpage.getRecords().stream().map(obj -> BeanUtil.toBean(obj, ChannelInfoVo.class)).collect(Collectors.toList());
        result.setList(infosVos);
        return result;
    }

    @Override
    public List<AgentInfo> getByParentId(long agentId) {
        return this.baseMapper.selectList(new QueryWrapper<AgentInfo>().eq("parent_id", agentId));
    }

    @Override
    public AgentStatsVo agentStats() {
        AgentInfo agentInfo = this.getById(StpAgentUtil.getLoginIdAsLong());
        if (agentInfo == null) {
            throw new ServiceException("无效数据");
        }
        AgentStatistics agentStatistics = agentStatisticsService.getByAgentId(agentInfo.getId());
        AgentStatsVo vo = new AgentStatsVo();
        vo.setAvailableAmount(agentInfo.getAvailableAmount());
        vo.setFreezeAmount(agentInfo.getFreezeAmount());
        vo.setSubLedgerAmount(agentStatistics.getCommissionAmount());
        vo.setType(agentInfo.getType());
        vo.setUpdateTime(agentStatistics.getUpdateTime() == null ? agentStatistics.getCreateTime() : agentStatistics.getUpdateTime());
        //直接商户总数
        vo.setDirectMerchantCount(agentStatistics.getShopInfoCount());
        //只有代理才查询，渠道商总数，间接商户总数
        if (vo.getType().equals(CommonConstants.NUMBER_ONE)) {
            vo.setChannalCount(agentStatistics.getChannalCount());
            //间接商户总数
            List<AgentInfo> child = this.getByParentId(agentInfo.getId());
            if (CollectionUtil.isNotEmpty(child)) {
                List<Long> agentId = child.stream().map(AgentInfo::getId).collect(Collectors.toList());
                vo.setInDirectMerchantCount(accountInfoService.count(new QueryWrapper<AccountInfo>().in("agent_id", agentId)));
            } else {
                vo.setInDirectMerchantCount(CommonConstants.NUMBER_ZERO);
            }
        }
        return vo;
    }

    @Override
    public void agentInfoMotify(AgentInfoMotifyDto agentAddChannelDto) {
        AgentInfo info = this.getById(StpAgentUtil.getLoginIdAsLong());
        AgentInfo agentInfo = new AgentInfo();
        agentInfo.setId(info.getId());
        if (StrUtil.isNotEmpty(agentAddChannelDto.getLinkName())) {
            agentInfo.setLinkName(agentAddChannelDto.getLinkName());
        }
        if (StrUtil.isNotEmpty(agentAddChannelDto.getPhone())) {
            sendCodeService.certificateCheck(agentAddChannelDto.getPhoneCodeCertificate(), info.getAccount(), AuthCodeEnum.AGENT_PHONE_INTIE.getType());
            agentInfo.setPhone(agentAddChannelDto.getPhone());
        }
        if (StrUtil.isNotEmpty(agentAddChannelDto.getPassword())) {
            sendCodeService.certificateCheck(agentAddChannelDto.getPasswordCodeCertificate(), info.getAccount(), AuthCodeEnum.AGENT_PASSWORD_INTIE.getType());
            agentInfo.setPwd(agentAddChannelDto.getPassword());
        }
        this.updateById(agentInfo);
    }

    @Override
    public AgentDetailInfo getByAgentId(Long agentId) {
        AgentInfo agentInfo = this.getById(agentId);
        AgentDetailInfo vo = BeanUtil.toBean(agentInfo, AgentDetailInfo.class);
        vo.setAgentType(agentInfo.getType());
        List<AgentRule> agentTarget = agentRuleService.getByAgenInfoIdAndRuleClass(agentInfo.getId(), CommonConstants.NUMBER_ONE);
        if (CollectionUtil.isNotEmpty(agentTarget)) {
            vo.setAgentTarget(agentTarget.stream()
                    .map(obj -> BeanUtil.toBean(obj, AgentRuleVo.class))
                    .collect(Collectors.toList()));
        }
        //渠道商需查出升级条件
        List<AgentRule> agentUpgrade = agentRuleService.getByAgenInfoIdAndRuleClass(agentInfo.getId(), CommonConstants.NUMBER_TWO);
        if (CollectionUtil.isNotEmpty(agentUpgrade)) {
            vo.setAgentUpgrade(agentUpgrade.stream()
                    .map(obj -> BeanUtil.toBean(obj, AgentRuleVo.class))
                    .collect(Collectors.toList()));
        }
        AgentBank agentBank = agentBankService.getByAgentId(agentId);
        if (agentBank != null) {
            CardBankVo bankVo = BeanUtil.toBean(agentBank, CardBankVo.class);
            bankVo.setBankId(agentBank.getId());
            vo.setBankInfo(bankVo);
        }
        return vo;
    }

    @Override
    public AgentDetailInfo getChannelInfo(Long agentId) {
        AgentInfo parentInfo = this.getById(StpAgentUtil.getLoginIdAsLong());
        if (!parentInfo.getType().equals(CommonConstants.NUMBER_ONE)) {
            throw new ServiceException("非法查看");
        }
        AgentInfo agentInfo = this.getById(agentId);
        if (agentInfo == null) {
            throw new ServiceException("无效数据");
        }
        if (!parentInfo.getId().equals(agentInfo.getParentId())) {
            throw new ServiceException("非所属渠道商");
        }
        AgentDetailInfo vo = BeanUtil.toBean(agentInfo, AgentDetailInfo.class);
        vo.setAgentType(agentInfo.getType());
        List<AgentRule> agentTarget = agentRuleService.getByAgenInfoIdAndRuleClass(agentInfo.getId(), CommonConstants.NUMBER_ONE);
        if (CollectionUtil.isNotEmpty(agentTarget)) {
            vo.setAgentTarget(agentTarget.stream()
                    .map(obj -> BeanUtil.toBean(obj, AgentRuleVo.class))
                    .collect(Collectors.toList()));
        }
        //渠道商需查出升级条件
        if (!agentInfo.getType().equals(CommonConstants.NUMBER_ONE)) {
            List<AgentRule> agentUpgrade = agentRuleService.getByAgenInfoIdAndRuleClass(agentInfo.getId(), CommonConstants.NUMBER_TWO);
            if (CollectionUtil.isNotEmpty(agentUpgrade)) {
                vo.setAgentUpgrade(agentUpgrade.stream()
                        .map(obj -> BeanUtil.toBean(obj, AgentRuleVo.class)).collect(Collectors.toList()));
            }
        }
        AgentBank agentBank = agentBankService.getByAgentId(agentId);
        if (agentBank != null) {
            CardBankVo bankVo = BeanUtil.toBean(agentBank, CardBankVo.class);
            bankVo.setBankId(agentBank.getId());
            vo.setBankInfo(bankVo);
        }
        return vo;
    }

    @Override
    public AgentInfo getByCode(String inviteCode) {
        return this.getOne(new QueryWrapper<AgentInfo>().eq("code", inviteCode));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void merchantsMigration(MerchantsMigrationDto migrationDto) {
        migrationAccount(migrationDto.getAgentId(), migrationDto.getAccountIds());
    }

    @Override
    public void validateAgentTarget() {
        //获取所有代理
        List<AgentInfo> agentInfos = this.baseMapper.selectList(new QueryWrapper<AgentInfo>()
                .eq("type", CommonConstants.NUMBER_ONE)
                .eq("status", CommonConstants.NUMBER_ONE)
        );
        for (AgentInfo agentInfo : agentInfos) {
            //判断代理是否目标条件
            List<AgentRule> tagertRule = agentRuleService.getByAgenInfoIdAndRuleClass(agentInfo.getId(), CommonConstants.NUMBER_ONE);
            //需达标数
            Integer conditionNumber = 0;
            //已达标数
            Integer upNumber = 0;
            //获取用户所有订单
            List<BigDecimal> paidPayable = sysShopPackageOrderService.selectByAgentOrder(agentInfo.getId());
            for (AgentRule agentRule : tagertRule) {
                //计算时间范围,判断是否达到需要
                //计算代理创建时间与当前时间相差几个月
                DateTime date = DateUtil.date();
                //开始时间距离当前时间相差多久
                long month = DateUtil.betweenMonth(LocalDateTimeUtils.convertLDTToDate(agentInfo.getCreateTime()), date, true);
                //如果值大于目标值，则需要进行时间间隔计算  例如：创建时间 1月1  当前时间相差8个，目标是3个月，则从创建时间开始每3个月计算1次 也就是9月1号时进行计算是否达标，仅打比喻
                //当天计算值不能被整除，未到达计算时间
                if (month == 0 || month % agentRule.getTargetTime() != 0) {
                    continue;
                }
                //销售总单数
                if (agentRule.getRuleType().equals(CommonConstants.NUMBER_ONE)) {
                    conditionNumber++;
                    //判断总单数是否达标
                    if (paidPayable.size() >= Integer.parseInt(agentRule.getTargetValue())) {
                        upNumber++;
                    }
                }
                //销售总额
                else if (agentRule.getRuleType().equals(CommonConstants.NUMBER_TWO)) {
                    conditionNumber++;
                    //判断销售额是否达标
                    double sum = paidPayable.stream().mapToDouble(BigDecimal::doubleValue).sum();
                    if (sum >= Double.parseDouble(agentRule.getTargetValue())) {
                        upNumber++;
                    }
                }
            }
            //需达标数大于0则已到计算日期
            if (conditionNumber > 0 && upNumber < conditionNumber) {
                AgentInfo up = new AgentInfo();
                up.setId(agentInfo.getId());
                //用户未达标则需要降级,变为直属渠道商
                up.setType(CommonConstants.NUMBER_TWO);
                up.updateById();
                //下级渠道商数据归0
                AgentStatistics statistics = agentStatisticsService.getByAgentId(agentInfo.getId());
                statistics.setChannalCount(0);
                statistics.updateById();
                //获取所有子渠道商,变为直属渠道商
                List<AgentInfo> subAgent = this.getByParentId(up.getId());
                if (CollectionUtil.isNotEmpty(subAgent)) {
                    for (AgentInfo info : subAgent) {
                        AgentInfo subUp = new AgentInfo();
                        subUp.setId(info.getId());
                        subUp.setType(CommonConstants.NUMBER_TWO);
                        subUp.updateById();
                    }
                }
            }

        }
    }

}
